package client

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"gin-epg/internal/app/dao"
	"gin-epg/internal/app/entity"
	"github.com/go-resty/resty/v2"
	"time"

	"crypto/sha256"
	"encoding/hex"
	"github.com/spf13/cast"
)

// HNTV 频道名称映射
var mapHntv = map[string]string{
	"154": "梨园",
	// 更多键值对...
}

// generateSignature 生成 SHA-256 签名
func generateSignature(message string) string {
	hash := sha256.New()
	hash.Write([]byte(message))
	hashBytes := hash.Sum(nil)
	return hex.EncodeToString(hashBytes)
}

// 获取当前 Unix 时间戳
func getCurrentTimestamp() int64 {
	return time.Now().Unix()
}

// 获取指定日期的开始时间戳（00:00:00）
func getStartOfDayTimestamp(dateStr string) (int64, error) {
	layout := "2006-01-02"
	t, err := time.Parse(layout, dateStr)
	if err != nil {
		return 0, err
	}
	startOfDay := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.UTC).Unix()
	return startOfDay, nil
}

// HandleHntvCron 处理 HNTV 节目单
func HandleHntvCron(beforeDay, afterDay int) error {
	dao.Logger.Infof("handleHntvCron start")
	source := "hntv"

	client := resty.New()
	for key, value := range mapHntv {
		dao.Logger.Infof("Key: %s, Value: %s", key, value)
		for dayOffset := -beforeDay; dayOffset <= afterDay; dayOffset++ {
			urlDate := time.Now().AddDate(0, 0, dayOffset).Format("2006-01-02")
			urlTimestamp, err := getStartOfDayTimestamp(urlDate)
			if err != nil {
				dao.Logger.Errorf("failed to get start of day timestamp for date %s: %v", urlDate, err)
				continue
			}

			// 固定密钥
			secret := "6ca114a836ac7d73"
			currentTimestamp := getCurrentTimestamp()
			signature := generateSignature(fmt.Sprintf("%s%d", secret, currentTimestamp))

			url := fmt.Sprintf("https://pubmod.hntv.tv/program/getAuth/vod/originStream/program/%s/%d", key, urlTimestamp)

			resp, err := client.R().
				SetHeaders(map[string]string{
					"sign":      signature,
					"timestamp": fmt.Sprintf("%d", currentTimestamp),
				}).
				Get(url)

			if err != nil {
				dao.Logger.Errorf("failed to get data from URL %s: %v", url, err)
				continue
			}

			var data map[string]interface{}
			if err := json.Unmarshal(resp.Body(), &data); err != nil {
				dao.Logger.Errorf("failed to unmarshal JSON from URL %s: %v", url, err)
				continue
			}

			if programs, ok := data["programs"]; ok {
				// 获取当前日期范围内的已有节目记录
				db := dao.SqlSession
				dateParsed, _ := time.Parse("2006-01-02", urlDate)
				var existingRecords []entity.EpgProgramCollect
				if err := db.Where(&entity.EpgProgramCollect{Channel: value, Date: entity.NullDate{sql.NullTime{Time: dateParsed, Valid: true}}, Source: source}).Find(&existingRecords).Error; err != nil {
					dao.Logger.Errorf("failed to get existing records: %v", err)
					continue
				}

				existingMap := make(map[string]*entity.EpgProgramCollect)
				for i := range existingRecords {
					existingMap[existingRecords[i].Start] = &existingRecords[i]
				}

				var newPrograms, updatePrograms, deletePrograms []entity.EpgProgramCollect

				for _, program := range programs.([]interface{}) {
					programMap := program.(map[string]interface{})
					startDate := cast.ToInt64(programMap["beginTime"])
					momentStartDate := time.Unix(startDate, 0)
					stopDate := cast.ToInt64(programMap["endTime"])
					momentStopDate := time.Unix(stopDate, 0)

					channel := value
					date := momentStartDate.Format("2006-01-02")
					start := momentStartDate.Format("15:04")
					stop := momentStopDate.Format("15:04")

					if channel != "" && date != "" && start != "" && stop != "" {
						title := cast.ToString(programMap["title"])
						desc := ""

						if existingRecord, ok := existingMap[start]; ok {
							if existingRecord.Title != title || existingRecord.End != stop {
								existingRecord.Title = title
								existingRecord.Desc = desc
								existingRecord.End = stop
								existingRecord.UpdateTime = entity.NullTime{sql.NullTime{Time: time.Now(), Valid: true}}
								updatePrograms = append(updatePrograms, *existingRecord)
							}
							delete(existingMap, start)
						} else {
							newRecord := entity.EpgProgramCollect{
								Title:      title,
								Desc:       desc,
								Source:     source,
								Channel:    channel,
								Date:       entity.NullDate{sql.NullTime{Time: dateParsed, Valid: true}},
								Start:      start,
								End:        stop,
								CreateTime: entity.NullTime{sql.NullTime{Time: time.Now(), Valid: true}},
							}
							newPrograms = append(newPrograms, newRecord)
						}
					}
				}

				// 处理需要删除的记录
				for _, record := range existingMap {
					deletePrograms = append(deletePrograms, *record)
				}

				// 执行数据库操作
				if len(updatePrograms) > 0 {
					for _, program := range updatePrograms {
						if err := db.Model(&program).Updates(entity.EpgProgramCollect{Title: program.Title, Desc: program.Desc, End: program.End, UpdateTime: program.UpdateTime}).Error; err != nil {
							dao.Logger.Errorf("update error: %v", err)
						} else {
							dao.Logger.Debugf("update success: %v", program)
						}
					}
				}

				if len(newPrograms) > 0 {
					for _, program := range newPrograms {
						if err := db.Create(&program).Error; err != nil {
							dao.Logger.Errorf("insert error: %v", err)
						} else {
							dao.Logger.Debugf("insert success: %v", program)
						}
					}
				}

				if len(deletePrograms) > 0 {
					for _, program := range deletePrograms {
						if err := db.Delete(&program).Error; err != nil {
							dao.Logger.Errorf("delete error: %v\n", err)
						} else {
							dao.Logger.Debugf("delete success", program)
						}
					}
				}
			}
		}
	}
	return nil
}
